#include "portproxy.h"

namespace cricket
{
	void PortProxy::set_impl(PortInterface* port)
	{
		impl_ = port;

		impl_->SignalUnknownAddress.connect(this, &PortProxy::OnUnknownAddress);
		impl_->SignalDestroyed.connect(this, &PortProxy::OnPortDestroyed);
		impl_->SignalRoleConflict.connect(this, &PortProxy::OnRoleConflict);
	}

	const std::string& PortProxy::Type() const
	{
		ASSERT(impl_ != NULL);
		return impl_->Type();
	}

	base::NetWork* PortProxy::NetWork() const
	{
		ASSERT(impl_ != NULL);
		return impl_->NetWork();
	}

	void PortProxy::SetIceProtocolType(IceProtocolType protocol)
	{
		ASSERT(impl_ != NULL);
		impl_->SetIceProtocolType(protocol);
	}

	IceProtocolType PortProxy::IceProtocol() const
	{
		ASSERT(impl_ != NULL);
		return impl_->IceProtocol();
	}

	// Methods to set/get ICE role and tiebreaker values.
	void PortProxy::SetRole(TransportRole role)
	{
		ASSERT(impl_ != NULL);
		impl_->SetRole(role);
	}

	TransportRole PortProxy::Role() const
	{
		ASSERT(impl_ != NULL);
		return impl_->Role();
	}

	void PortProxy::SetTiebreaker(uint64 tiebreaker)
	{
		ASSERT(impl_ != NULL);
		impl_->SetTiebreaker(tiebreaker);
	}

	uint64 PortProxy::Tiebreaker() const
	{
		ASSERT(impl_ != NULL);
		return impl_->Tiebreaker();
	}

	bool PortProxy::SharedSocket() const {
		ASSERT(impl_ != NULL);
		return impl_->SharedSocket();
	}

	void PortProxy::PrepareAddress() {
		ASSERT(impl_ != NULL);
		impl_->PrepareAddress();
	}

	Connection* PortProxy::CreateConnection(const Candidate& remote_candidate,
		CandidateOrigin origin)
	{
		ASSERT(impl_ != NULL);
		return impl_->CreateConnection(remote_candidate, origin);
	}

	int PortProxy::SendTo(const void* data, size_t size, 
		const base::SocketAddress& addr, bool payload)
	{
		ASSERT(impl_ != NULL);
		return impl_->SendTo(data, size, addr, payload);
	}

	int PortProxy::SetOption(base::Socket::Option opt, int value)
	{
		ASSERT(impl_ != NULL);
		return impl_->SetOption(opt, value);
	}

	int PortProxy::GetOption(base::Socket::Option opt, int* value)
	{
		ASSERT(impl_ != NULL);
		return impl_->GetOption(opt, value);
	}

	int PortProxy::GetError()
	{
		ASSERT(impl_ != NULL);
		return impl_->GetError();
	}

	const std::vector<Candidate>& PortProxy::Candidates() const
	{
		ASSERT(impl_ != NULL);
		return impl_->Candidates();
	}

	void PortProxy::SendBindingResponse(StunMessage* request, 
		const base::SocketAddress& addr)
	{
		ASSERT(impl_ != NULL);
		return impl_->SendBindingResponse(request, addr);
	}

	Connection* PortProxy::GetConnection(const base::SocketAddress& remote_addr)
	{
		ASSERT(impl_ != NULL);
		return impl_->GetConnection(remote_addr);
	}

	void PortProxy::SendBindingErrorResponse(
		StunMessage* request, const base::SocketAddress& addr, 
		int error_code, const std::string& reason)
	{
		ASSERT(impl_ != NULL);
		return impl_->SendBindingErrorResponse(request, addr, error_code, reason);
	}

	void PortProxy::EnablePortPackets()
	{
		ASSERT(impl_ != NULL);
		return impl_->EnablePortPackets();
	}

	std::string PortProxy::ToString()
	{
		ASSERT(impl_ != NULL);
		return impl_->ToString();
	}

	void PortProxy::OnUnknownAddress(
		PortInterface *port,
		const talk_base::SocketAddress &addr,
		ProtocolType proto,
		IceMessage *stun_msg,
		const std::string &remote_username,
		bool port_muxed)
	{
		ASSERT(port == impl_);
		ASSERT(!port_muxed);
		SignalUnknownAddress(this, addr, proto, stun_msg, remote_username, true);
	}

	void PortProxy::OnRoleConflict(PortInterface* port)
	{
		ASSERT(port == impl_);
		SignalRoleConflict(this);
	}

	void PortProxy::OnPortDestroyed(PortInterface* port)
	{
		ASSERT(port == impl_);
		// |port| will be destroyed in PortAllocatorSessionMuxer.
		SignalDestroyed(this);
	}
}